import { any } from "../../core/logic";
import { guid} from "../../core/utils";
import { Channel } from "./Channel";
import { EventType,Event } from "../../event/index";
import { Component,ComponentType } from "../Component";
/**
 * 动画类，其构成：
 * 1. 一个Animation由1-n个Channel构成;
 * 2. 一个Chinnel由1-n个Sampler构成。
 * @class
 * @memberof w.animation
 * @extends Clock
 * @example
 *  let aniSys=new w.animation.AnimationSystem();
 *  let sampler=new w.animation.Sampler([0,40], [[0,0],[-100,0]],"LINEAR", "none");
 *  let channel=new w.animation.Channel(m,"map_uvOffset");
 *  channel.add(sampler);
 *  let animation=new w.animation.Animation({id:"uvOffset",running:true});
 *  animation.add(channel);
 *  aniSys.add(animation);
 */
class Animation extends Component{
    /**
     * 创建一个动画实例。
     * @constructor 
     * @param {String} opts.id 【可选】动画的id，缺省值:自动生成guid。
     * @param {Number} opts.loop 【可选】动画循环次数，缺省值:1。如需不限次数重复执行，可以将该参数值设置为：0。
     * @param {Boolean} opts.keep 【可选】动画执行结束是否保留,缺省值：true。如果保留，那么通过动画的start还可以再次启动，否则在执行结束后自动销毁。
     */
    constructor(opts={}){
        opts.type=ComponentType.Animation;
        super(opts);
        this.id=any(opts.id,guid());
        this.loop=any(opts.loop,1);
        this.keep=any(opts.keep,true);
        this.channels=[];
        this.autoStart = any(opts.autoStart,true);
		this.startTime = 0;
		this.oldTime = 0;
		this.elapsedTime = 0;
		this.running = false;
    }
    /**
	 * 开始动画。
	 * @method start
	 */
	start() {
		this.startTime = now();
		this.oldTime = this.startTime;
		this.elapsedTime = 0;
		this.running = true;
        this.play();
	}
	/**
	 * 停止动画
	 * @method stop
	 */
	stop() {
		this.getElapsedTime();
		this.running = false;
		this.autoStart = false;
	}
	/**
	 * 获取动画流逝的时间，单位:秒(s)。
	 * @method getElapsedTime 
	 * @returns {Number}
	 */
	getElapsedTime() {
		this.getDelta();
		return this.elapsedTime;//经过了多少时间
	}
	getDelta() {
		let diff = 0;
		if ( this.autoStart && ! this.running ) {
			this.start();//获取开始时间
			return 0;
		}
		if ( this.running ) {
			const newTime = now();
			diff = ( newTime - this.oldTime ) / 1000;
			this.oldTime = newTime;
			this.elapsedTime += diff;
		}
		return diff;
	}
    /**
     * @property {String} id 动画的唯一标识。
     */
    set id(v){
        this._id=v;
        return this;
    }
    get id(){
        return this._id;
    }
    /**
     * @property {Number} loop 动画循环次数。
     */
    set loop(v){
        this._loop=v;
        return this;
    }
    get loop(){
        return this._loop;
    }
    /**
     * @property {Boolean} keep 动画执行完成是否保留。
     */
    set keep(v){
        this._keep=v;
        return this;
    }
    get keep(){
        return this._keep;
    }

    /**
     * 添加动画通道。
     * @method
     * @param {w.animation.Channel} channel 
     * @return {w.animation.Animation} 返回添加Channel后的Animation对象。
     */
    add(channel){
        let index=this.channels.indexOf(channel);
        if(index>=0){
            this.channels.splice(index,1);    
        }
        this.channels.push(channel);
        return this;
    }
    /**
     * 移除指定动画通道。
     * @method
     * @param {w.animation.Channel} channel 
     * @return {w.animation.Animation} 返回添加Channel后的Animation对象。
     */
    remove(channel){
        let id="";
        if(channel instanceof Channel){
            id=channel.id;
        }else{
            id=channel;
        }
        for(let i=this.channels.length-1;i>=0;i--){
            if(this.channels[i].id===id){
                this.channels.splice(i,1);
                break;
            }
        }
        return this;
    }
    /**
     * 移除所有动画通道。
     * @method
     * @return {Animation} 返回添加Channel后的Animation对象。
     */
    clear(){
        this.channels=[];
        return this;
    }
    play(){
        if(!this.running && !this.autoStart){
            return;
        }
        let playTime=this.getPlayTime();
        for(let i=0;i<this.channels.length;i++){
            this.channels[i].play(playTime);
        }
    }
    getPlayTime(){
        let dual=this.timeLine()[1];//最大时间
        let playTime=0;
        if(this.loop==0){
            playTime=this.getElapsedTime()%dual;//经历这个周期之后，剩余多少s
        }else{
            playTime=this.getElapsedTime();
            if(playTime>dual*this.loop){
                playTime=dual;
                this.stop();
                let event=new Event(EventType.AnimationCompleted);
                event.target=this;
                this.publish(event)
            }else{
                playTime=playTime%dual;
            }
        }
        return playTime;
    }
    timeLine(){
        let min=Number.MAX_VALUE,max=Number.MIN_VALUE;
        for(let i=0;i<this.channels.length;i++){
            const channels=this.channels[i];
            let timeLine=channels.timeLine();
            min=Math.min(min,timeLine[0]);
            max=Math.max(max,timeLine[1]);
        }
        return [min,max];
    }
    
}
function now() {
	return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
}
export {Animation}